﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using Casamiel.API.Application.Models.Jddj;
using Casamiel.API.Infrastructure;
using Casamiel.Common.Extensions;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using static Casamiel.API.Application.Models.Jddj.CreateTime;

// For more information on enabling Web API for empty projects, visit https://go.microsoft.com/fwlink/?LinkID=397860

namespace Casamiel.API.Controllers.V2
{
	/// <summary>
	/// 
	/// </summary>
    [Produces("application/json")]
    [ApiVersion("2.0")]
    [Route("api/v{api-version:apiVersion}/[controller]")]
    public class JddjController : Controller
    {
        //    "app_token": "28969a33-4f11-415f-af9e-3672df6e4ef1",
        //"app_key": "6920bc31a03e4de0862bd30c1560e428",
        //"app_secret": "2ec3be0446de44958bc5f4dc01d76547"
        private readonly string app_key = "6920bc31a03e4de0862bd30c1560e428";
        private readonly string format = "json";
        private readonly string token = "28969a33-4f11-415f-af9e-3672df6e4ef1";
        private readonly string appSecret = "2ec3be0446de44958bc5f4dc01d76547";
        private readonly string v = "1.0";
        private readonly string apiurl = "https://openo2o.jd.com";
        private readonly ICacheService _cacheService;
        /// <summary>
        /// Initializes a new instance of the <see cref="T:Casamiel.API.Controllers.V2.JddjController"/> class.
        /// </summary>
        /// <param name="cacheService">Cache service.</param>
        public JddjController(ICacheService cacheService){
            _cacheService = cacheService;
        }
        private async Task<string> HttpGet(string url, string jd_param_json)
        {
            var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            string strXXX = string.Format("app_key{0}format{1}jd_param_json{2}timestamp{3}token{4}v{5}", app_key, format, jd_param_json, timestamp, token, v);
            string strSign = string.Format("{0}{1}{0}", appSecret, strXXX);
            var sign = GetMd5Hash(strSign, false).ToUpper();
            Dictionary<string, string> parame = new Dictionary<string, string>();
            parame.Add("app_key", app_key);
            parame.Add("format", format);
            parame.Add("jd_param_json", jd_param_json);
            parame.Add("timestamp", timestamp);
            parame.Add("token", token);
            parame.Add("v", v);
            parame.Add("sign", sign);
            StringBuilder strUrl = new StringBuilder(apiurl + url);
            int i = 0;
            foreach (var key in parame.Keys)
            {
                strUrl.AppendFormat("{0}{1}={2}", ++i > 1 ? "&" : "?", key, parame[key]);
            }
            var _client = new HttpClient();
            var r = await _client.GetAsync(strUrl.ToString());
            return await r.Content.ReadAsStringAsync();
        }

        private async Task<string>PostAsync(string url,string jd_param_json){
            var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            string strXXX = string.Format("app_key{0}format{1}jd_param_json{2}timestamp{3}token{4}v{5}", app_key, format, jd_param_json, timestamp, token, v);
            string strSign = string.Format("{0}{1}{0}", appSecret, strXXX);
            var sign = GetMd5Hash(strSign, false).ToUpper();
             
            var _client = new HttpClient();
            List<KeyValuePair<String, String>> paramList = new List<KeyValuePair<String, String>>();
            paramList.Add(new KeyValuePair<String, String>("app_key", app_key));
            paramList.Add(new KeyValuePair<string, string>("jd_param_json", jd_param_json));
            paramList.Add(new KeyValuePair<String, String>("format", format));
            paramList.Add(new KeyValuePair<String, String>("timestamp", timestamp));
            paramList.Add(new KeyValuePair<String, String>("token", token));
            paramList.Add(new KeyValuePair<String, String>("sign", sign));
            paramList.Add(new KeyValuePair<String, String>("v", v));


            var request = new HttpRequestMessage(HttpMethod.Post, $"{apiurl}{url}");
            request.Content = new FormUrlEncodedContent(paramList);
           
           var response  = await   _client.SendAsync(request);
            if (response.IsSuccessStatusCode)
            {
                return await response.Content.ReadAsStringAsync();
            }
            //todo:
            return "";
           }
        /// <summary>
        /// Gets the stations by vender identifier.
        /// </summary>
        /// <returns>The stations by vender identifier.</returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult> getStationsByVenderId()
        {
            var result = await HttpGet("/djapi/store/getStationsByVenderId", "{}");
            var model = JsonConvert.DeserializeObject<djRsp>(result);
            if (model != null)
            {
                if (model.code == "0")
                {
                    var rnt = JsonConvert.DeserializeObject<JObject>(model.data);
                    if (rnt["code"].ToString() == "1")
                    {
                        var list = JsonConvert.DeserializeObject<List<string>>(rnt["result"].ToString());
                        var storeList = new Dictionary<string, string>();
                        foreach (var item in list)
                        {
                            var ent = await GetStoreInfo(item);
                            if (ent != null)
                            {
                                storeList.Add(item, ent.outSystemId);
                            }
                        }
                        return Ok(storeList);
                    }
                }
            }

            return Ok(model);
        }

        private async Task<List<string>>GetStations(){
            var result = await HttpGet("/djapi/store/getStationsByVenderId", "{}");
            var model = JsonConvert.DeserializeObject<djRsp>(result);
            if (model != null)
            {
                if (model.code == "0")
                {
                    var rnt = JsonConvert.DeserializeObject<JObject>(model.data);
                    if (rnt["code"].ToString() == "1")
                    {
                        var list = JsonConvert.DeserializeObject<List<string>>(rnt["result"].ToString());
                        return list;
                    }
                }
            }
            return null;

        }
        /// <summary>
        /// Queries the sku infos.
        /// </summary>
        /// <returns>The sku infos.</returns>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult> querySkuInfos()
        {
            var skuinfos = await _cacheService.GetAsync<List<SkuMain>>(app_key+"SkuInfos");
            if(skuinfos!=null){
                List<string> storelist = await GetStations();
                if (storelist.Count > 20)
                {
                    var ppsize = Math.Max((storelist.Count) / 4, 1);

                    ParallelLoopResult parallelLoopResult = Parallel.For(1, 4, i =>
                    {
                        var l = storelist.Skip((i - 1) * ppsize).Take(ppsize);
                        foreach (var item in l)
                        {
                            var storeInfo = GetStoreInfo(item);
                            storeInfo.Wait();
                            var abc = storeInfo.Result;

                            Console.WriteLine($"{i}-{item}:{JsonConvert.SerializeObject(abc)}");
                        }
                        Console.WriteLine($"{i},{JsonConvert.SerializeObject(l)}");
                    });
                    Console.WriteLine("是否完成:{0}", parallelLoopResult.IsCompleted);
                }
                return Ok(skuinfos);
            }
            skuinfos = new List<SkuMain>();
            var url = "/djapi/pms/querySkuInfos";
            var pageSize = 20;
            var pageNo = 1;
            var data = new { pageNo = pageNo, pageSize = 20 };
            var result = await HttpGet(url, JsonConvert.SerializeObject(data));
            var model = JsonConvert.DeserializeObject<djRsp>(result);
            if (model != null)
            {
                if (model.code == "0")
                {
                    var rnt = JsonConvert.DeserializeObject<JObject>(model.data);
                    if (rnt["code"].ToString() == "0")
                    {
                        var info = JObject.Parse(rnt["result"].ToString());
                        var totalCount = info["count"].ToInt32(0);
                        var lists=JsonConvert.DeserializeObject<List<SkuMain>>(info["result"].ToString());
                        skuinfos=lists;
                        var pagecount = Math.Max((totalCount + pageSize - 1) / pageSize, 1);

                        for (int i = 2; i< pagecount;i++){
                             
                            var result1 = await HttpGet(url, JsonConvert.SerializeObject(new { pageNo = i, pageSize = 20 }));
                            var model1 = JsonConvert.DeserializeObject<djRsp>(result1);
                            if (model1.code == "0")
                            {
                                var rnt1 =JObject.Parse(model1.data);
                                if (rnt1["code"].ToString() == "0")
                                {
                                    var info1 = JObject.Parse(rnt1["result"].ToString());
                                    var lists1 = JsonConvert.DeserializeObject<List<SkuMain>>(info1["result"].ToString());
                                    skuinfos= skuinfos.Union(lists1).ToList();
                                }
                            }
                        }
                        await _cacheService.AddAsync(app_key + "SkuInfos", skuinfos);
                        List<string> storelist = await GetStations();
                        if(storelist.Count>20){
                            var ppsize = Math.Max((storelist.Count) / 4, 1);

                            ParallelLoopResult  parallelLoopResult =  Parallel.For(1,4,i=>
                            {
                                var l= storelist.Skip((i - 1) * ppsize).Take(ppsize);
                                Console.WriteLine($"{i},{JsonConvert.SerializeObject(l)}");
                            });
                            Console.WriteLine("是否完成:{0}", parallelLoopResult.IsCompleted);
                        }


                        return Ok(skuinfos);
                    }
                }
            }
            return Ok(model);
        }
        /// <summary>
        /// Dd this instance.
        /// </summary>
        /// <returns>The dd.</returns>
        /// <remarks>{"StoreNo":"111"}</remarks>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult> getStoreInfoByStationNo([FromBody]JObject data)
        {
            var model = await GetStoreInfo(data["StoreNo"].ToString());
            return Ok(model);
        }
        /// <summary>
        /// Batchs the update current qtys.
        /// </summary>
        /// <returns>The update current qtys.</returns>
        /// <param name="stationNo">Station no.</param>
        [HttpPost]
        [Route("[action]")]
        public async Task<IActionResult>batchUpdateCurrentQtys(string stationNo){
            var result = await updateOpenLockQtys();
            var model = JsonConvert.DeserializeObject<djRsp>(result);
            //if (model != null)
            //{
            //    if (model.code == "0")
            //    {
            //        var rnt = JsonConvert.DeserializeObject<JObject>(model.data);
            //        if (rnt["code"].ToString() == "1")
            //        {
            //            var list = JsonConvert.DeserializeObject<List<string>>(rnt["result"].ToString());
            //            return list;
            //        }
            //    }
            //}
            return Ok(model);
        }
        private async Task<string> updateOpenLockQtys()
        {
            var url = "/djapi/stock/batchUpdateCurrentQtys";
            var skulist =new  List<SkuStock>();
            skulist.Add( new SkuStock { outSkuId = "410068", stockQty = "99" });
            skulist.Add(new SkuStock { outSkuId = "417132", stockQty = "99" });
            var data = new { stationNo = "11766903", userPin = "casamiel", skuStockList = skulist };
            return await PostAsync(url, JsonConvert.SerializeObject(data));
        }
        private async Task<StoreInfo> GetStoreInfo(string StoreNo)
        {

            var jd_param_json = JsonConvert.SerializeObject(new { StoreNo = StoreNo });
            var url = "/djapi/storeapi/getStoreInfoByStationNo";
            var result = await HttpGet(url, jd_param_json);
            var model = JsonConvert.DeserializeObject<djRsp>(result);
            if (model != null)
            {
                if (model.code == "0")
                {
                    var rnt = JsonConvert.DeserializeObject<JObject>(model.data);
                    if (rnt["code"].ToString() == "0")
                    {
                        var info = JsonConvert.DeserializeObject<StoreInfo>(rnt["result"].ToString());
                        return info;
                    }
                }
            }
            return null;
        }
        /// <summary>
        /// Dj rsp.
        /// </summary>
        public class djRsp
        {
            /// <summary>
            /// Gets or sets the code.
            /// </summary>
            /// <value>The code.</value>
            public string code { get; set; }
            /// <summary>
            /// Gets or sets the message.
            /// </summary>
            /// <value>The message.</value>
            public string msg { get; set; }
            /// <summary>
            /// Gets or sets the data.
            /// </summary>
            /// <value>The data.</value>
            public string data { get; set; }
        }
		/// <summary>
		/// 
		/// </summary>
        public class SkuStock
        {
            /// <summary>
            /// Gets or sets the out sku identifier.
            /// </summary>
            /// <value>The out sku identifier.</value>
            public string outSkuId { get; set; }
            /// <summary>
            /// Gets or sets the stock qty.
            /// </summary>
            /// <value>The stock qty.</value>
            public string stockQty { get; set; }
        }
        private string GetMd5Hash(string strMsg, bool isDefaultEncoding = true)
        {
            MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
            byte[] data = md5Hasher.ComputeHash(isDefaultEncoding ? Encoding.Default.GetBytes(strMsg) : Encoding.UTF8.GetBytes(strMsg));
            StringBuilder sBuilder = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sBuilder.Append(data[i].ToString("x2"));
            }
            return sBuilder.ToString();
        }
    }
}
